package com.example.demo.jdk.jvm.classloader.swap;

import org.elasticsearch.common.util.set.Sets;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @author: htc
 * @date: Created in 17:24 2019/3/7.
 */
public class TestMain {
    /***
     * 写个定时任务，一直调用printVersion方法，观察输出，看我们是否替换成功。
     * @param args
     */
    public static void main(String[] args) {
        String swapPath = MyClassLoader.class.getResource("").getPath();
        String className = "com.example.demo.jdk.jvm.classloader.swap.Test";

        //每次都实例化一个ClassLoader，这里传入swap路径，和需要特殊加载的类名
        MyClassLoader myClassLoader = new MyClassLoader(swapPath, Sets.newHashSet(className));
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {

                try {
                    //使用自定义的ClassLoader加载类，并调用printVersion方法。
                    Object o = myClassLoader.loadClass(className).newInstance();

                    //调用方法一（正确）
                    o.getClass().getMethod("printVersion").invoke(o);
                    System.out.println("当前类加载器：" + o.getClass().getClassLoader());
                    System.out.println("父类加载器："+o.getClass().getClassLoader().getParent());

                    //调用方法二(错误),这种写法会导致抛出ClassCastException异常，
                    //Test.class会隐性的被加载当前类的ClassLoader加载，当前Main方法默认的ClassLoader为AppClassLoader， 而不是我们自定义的MyClassLoader。
                    // 一个类，就算包路径完全一致，但是加载他们的ClassLoader不一样，那么这两个类也会被认为是两个不同的类。
//                    Test test = (Test) o;
//                    test.printVersion();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 0, 2000);
    }
}
